home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / AppleShare API / Extras / ServerControlSnippets.p < prev    next >
Encoding:
Text File  |  1995-01-03  |  24.6 KB  |  848 lines  |  [TEXT/MPS ]

  1. {===========================================================}
  2. {                                                            }
  3. { Server Control Snippets                                    }
  4. { The server control code snippets found in the                }
  5. { AppleShare 3.0 Developer's Kit Server Control and Server    }
  6. { Event Handling document.                                    }
  7. {                                                            }
  8. { by J. Luther, Apple Developer Technical Support            }
  9. { Copyright Apple Computer, Inc. 1992-1994                    }
  10. { All rights reserved                                        }
  11. {                                                            }
  12. { Updated for File Sharing 4.0 - 9/8/1994 JML                }
  13. {                                                            }
  14. { Here's the deal with the code in this file.                }
  15. {                                                            }
  16. { For each server control call, there is a function named    }
  17. { MySCxxxx. The typical MySCxxxx function shows how to        }
  18. { fill in the parameter block, make the server control        }
  19. { call, and return any result values the server control        }
  20. { returns.  In addition, I've made every attempt to make    }
  21. { the server control calls supported by Macintosh File        }
  22. { Sharing act like the same server control calls under        }
  23. { AppleShare 3.0.  In some cases, that means I've filled    }
  24. { in the return values not supplied by Macintosh File        }
  25. { Sharing.  In other cases (i.e., SCGetExpFldr), I've had    }
  26. { to add code just to make the server control call work as    }
  27. { advertised.                                                }
  28. {                                                            }
  29. { For some server control calls, I've added another code    }
  30. { snippet, procedure, or function to show a common use of    }
  31. { that particular server control call.  Here's what you'll    }
  32. { find:                                                        }
  33. {                                                            }
  34. { • There are code snippets that get the server version,    }
  35. { status, and setup information and then store that            }
  36. { information in global variables for later use by other    }
  37. { functions.  In some case, other code depends on those        }
  38. { global variables being initialized and that is noted        }
  39. { where applicable.                                            }
  40. {                                                            }
  41. { • There are functions and procedures that show how to        }
  42. { enumerate the list of exported volumes and folder,        }
  43. { enumerate the list of installed server event handlers,    }
  44. { enumerate the list of connected users, get a users mount    }
  45. { information for all volumes or folders mounted,            }
  46. { disconnect a user from the server, send a message to all    }
  47. { connected users, and disconnect the users of a specified    }
  48. { volume.                                                    }
  49. {                                                            }
  50. { All the test functions and snippets are marked like        }
  51. { this: ••• Test Code •••                                    }
  52. { Some code snippets are commented out under the Test Code    }
  53. { markers, because they won't compile there.  They can be    }
  54. { found again between the main BEGIN and END.                }
  55. {                                                            }
  56. {===========================================================}
  57.  
  58. PROGRAM SC_Snippets;
  59.  
  60.     USES
  61.         Traps, AppleTalk, Errors, Memory, ServerEventIntf, ServerControlIntf;
  62.  
  63.     { File Sharing 4.0 supports most server control calls just like AppleShare.    }
  64.     { The only exceptions are SCShutDown and SCDisconnect which ignore the        }
  65.     { flags and messagePtr parameters because those calls were supported by        }
  66.     { the old File Sharing code and some callers didn't bother to set            }
  67.     { messagePtr to NULL.                                                        }
  68.  
  69.     CONST
  70.         kNewFileSharingVersion = $3e;    { File Sharing 4.0's version number }
  71.  
  72.     TYPE
  73.         Str13 = STRING[13];
  74.  
  75.     VAR
  76.         gErr: OSErr;
  77.         gHasServerDispatch: Boolean;
  78.  
  79.         { results from SCServerVersion }
  80.         gServerExtensionName: Str31;
  81.         gServerType: Integer;
  82.         gServerVersion: Integer;
  83.  
  84.         { results from SCPollServer }
  85.         gServerState: Integer;
  86.         gDisconnectState: Integer;
  87.         gServerError: Integer;
  88.         gSecondsLeft: LongInt;
  89.  
  90.         { results from SCGetSetupInfo }
  91.         gSetupInfoRec: SetupInfoRec;
  92.         gMaxVolumes: Integer;
  93.         gMaxExpFolders: Integer;
  94.         gCurMaxSessions: Integer;
  95.  
  96. {=======================================================================================}
  97. { the following three functions (NumToolboxTraps, GetTrapType, and TrapAvailable) }
  98. { are from Inside Macintosh Volume VI. }
  99.  
  100.     FUNCTION NumToolboxTraps: Integer;
  101.     BEGIN
  102.         IF NGetTrapAddress(_InitGraf, ToolTrap) = NGetTrapAddress($AA6E, ToolTrap) THEN
  103.             NumToolboxTraps := $200
  104.         ELSE
  105.             NumToolboxTraps := $400;
  106.     END;
  107.  
  108. {------------------------------------------------------------------------------------}
  109.  
  110.     FUNCTION GetTrapType (theTrap: Integer): TrapType;
  111.         CONST
  112.             TrapMask = $0800;
  113.     BEGIN
  114.         IF BAND(theTrap, TrapMask) > 0 THEN
  115.             GetTrapType := ToolTrap
  116.         ELSE
  117.             GetTrapType := OSTrap;
  118.     END;
  119.  
  120. {------------------------------------------------------------------------------------}
  121.  
  122.     FUNCTION TrapAvailable (theTrap: Integer): Boolean;
  123.         VAR
  124.             tType: TrapType;
  125.     BEGIN
  126.         tType := GetTrapType(theTrap);
  127.         IF tType = ToolTrap THEN
  128.             BEGIN
  129.                 theTrap := BAND(theTrap, $07FF);
  130.                 IF theTrap >= NumToolboxTraps THEN
  131.                     theTrap := _Unimplemented;
  132.             END;
  133.         TrapAvailable := NGetTrapAddress(theTrap, tType) <> NGetTrapAddress(_Unimplemented, ToolTrap)
  134.     END;
  135.  
  136. {=======================================================================================}
  137.  
  138. {-----------------------------------------------------------}
  139. { This function calls SCServerVersion to get the file        }
  140. { server extension's name and the server's type and            }
  141. { version.                                                    }
  142. { Note: The server version (scServerVersion) returned by    }
  143. {       Macintosh File Sharing servers is not valid when    }
  144. {       the file server is not running.                        }
  145.  
  146.     FUNCTION MySCServerVersion (ExtNamePtr: StringPtr;
  147.                                     VAR ServerType: Integer;
  148.                                     VAR ServerVersion: Integer): OSErr;
  149.         VAR
  150.             scPB: SCParamBlockRec;
  151.     BEGIN
  152.         scPB.versionPB.scCode := SCServerVersion;
  153.         scPB.versionPB.scExtNamePtr := ExtNamePtr;
  154.  
  155.         MySCServerVersion := SyncServerDispatch(@scPB);
  156.  
  157.         ServerType := scPB.versionPB.scServerType;
  158.         ServerVersion := scPB.versionPB.scServerVersion;
  159.     END;
  160.  
  161. {••• Test Code •••}
  162. { Get the server version information and store it in        }
  163. { global variables for user later                            }
  164.  
  165. (* err := MySCServerVersion(@gServerExtensionName, gServerType, gServerVersion); *)
  166.  
  167.  
  168. {-----------------------------------------------------------}
  169. { This function calls SCPollServer to find out what the        }
  170. { server is doing.                                            }
  171.  
  172.     FUNCTION MySCPollServer (VAR ServerState: Integer;
  173.                                     VAR DisconnectState: Integer;
  174.                                     VAR ServerError: Integer;
  175.                                     VAR SecondsLeft: LongInt): OSErr;
  176.         VAR
  177.             scPB: SCParamBlockRec;
  178.     BEGIN
  179.         scPB.pollServerPB.scCode := SCPollServer;
  180.           { Macintosh File Sharing doesn't return scSecondsLeft so zero it. }
  181.         scPB.pollServerPB.scSecondsLeft := 0;
  182.  
  183.         MySCPollServer := SyncServerDispatch(@scPB);
  184.  
  185.         ServerState := scPB.pollServerPB.scServerState;
  186.         DisconnectState := scPB.pollServerPB.scDisconnectState;
  187.         ServerError := scPB.pollServerPB.scServerError;
  188.         SecondsLeft := scPB.pollServerPB.scSecondsLeft;
  189.     END;
  190.  
  191. {••• Test Code •••}
  192. { Find out what the server's doing and store it in            }
  193. { global variables for user later                            }
  194.  
  195. (* err := MySCPollServer(gServerState, gDisconnectState, gServerError, gSecondsLeft); *)
  196.  
  197.  
  198. {-----------------------------------------------------------}
  199. { This function calls SCGetSetupInfo to get the file        }
  200. { server's setup information. If the server type is a        }
  201. { Macintosh File Sharing server, then this function fills    }
  202. { in the fields that aren't returned by the server control    }
  203. { call. This function depends on gServerType and            }
  204. { gServerVersion being initialized with SCServerVersion.    }
  205.  
  206.     FUNCTION MySCGetSetupInfo (SetupPtr: SetupInfoRecPtr;
  207.                                     VAR MaxVolumes: Integer;
  208.                                     VAR MaxExpFolders: Integer;
  209.                                     VAR CurMaxSessions: Integer): OSErr;
  210.         VAR
  211.             scPB: SCParamBlockRec;
  212.     BEGIN
  213.         scPB.setupPB.scCode := SCGetSetupInfo;
  214.         scPB.setupPB.scSetupPtr := SetupPtr;
  215.  
  216.         MySCGetSetupInfo := SyncServerDispatch(@scPB);
  217.  
  218.         IF (gServerType = MFSType) AND (gServerVersion < kNewFileSharingVersion) THEN
  219.             BEGIN
  220.                 MaxVolumes := 10;
  221.                 MaxExpFolders := 10;
  222.                 CurMaxSessions := SetupPtr^.SIMaxLogins;
  223.             END
  224.         ELSE
  225.             BEGIN
  226.                 MaxVolumes := scPB.setupPB.scMaxVolumes;
  227.                 MaxExpFolders := scPB.setupPB.scMaxExpFolders;
  228.                 CurMaxSessions := scPB.setupPB.scCurMaxSessions;
  229.             END;
  230.     END;
  231.  
  232. {••• Test Code •••}
  233. { Get the server's setup information and store it in        }
  234. { global variables for user later                            }
  235.  
  236. (* err := MySCGetSetupInfo(@gSetupInfoRec, gMaxVolumes, gMaxExpFolders, gCurMaxSessions); *)
  237.  
  238.  
  239. {-----------------------------------------------------------}
  240. { This function calls SCGetExpFldr to get the export        }
  241. { information for shared volumes and folders at the index    }
  242. { position specified. This function depends on gServerType    }
  243. { being initialized with SCServerVersion.                    }
  244.  
  245.     FUNCTION MySCGetExpFldr (NamePtr: StringPtr;
  246.                                     VAR VRefNum: Integer;
  247.                                     VAR Logins: Integer;
  248.                                     Index: Integer;
  249.                                     VAR DirID: LongInt): OSErr;
  250.         VAR
  251.             scPB: SCParamBlockRec;
  252.     BEGIN
  253.         scPB.standardPB.scCode := SCGetExpFldr;
  254.         { Initialize scVRefNum to 0 so we can tell if }
  255.         { SCGetExpFldr returned something when used with }
  256.         { Macintosh File Sharing }
  257.         scPB.standardPB.scVRefNum := 0;
  258.         IF Index < 0 THEN
  259.             BEGIN
  260.                 { File Sharing trashes memory if (scIndex < 0) and }
  261.                 { (scNamePtr <> NIL), so we'll prevent that from }
  262.                 { happening here. }
  263.                 scPB.standardPB.scNamePtr := NIL;
  264.                   { and we'll return an empty string }
  265.                 IF NamePtr <> NIL THEN
  266.                     NamePtr^ := '';
  267.             END
  268.         ELSE
  269.             BEGIN
  270.                 scPB.standardPB.scNamePtr := NamePtr;
  271.             END;
  272.         scPB.standardPB.scIndex := Index;
  273.  
  274.         MySCGetExpFldr := SyncServerDispatch(@scPB);
  275.  
  276.         IF (gServerType = MFSType) AND (gServerVersion < kNewFileSharingVersion) THEN
  277.             BEGIN
  278.                 IF scPB.standardPB.scVRefNum <> 0 THEN
  279.                     BEGIN
  280.                         VRefNum := scPB.standardPB.scVRefNum;
  281.                         Logins := 0;
  282.                         DirID := scPB.standardPB.scDirID;
  283.                     END
  284.                 ELSE  { there's nothing at this index position }
  285.                           { so force the error code to make it act }
  286.                           { like AppleShare }
  287.                     MySCGetExpFldr := fnfErr;
  288.             END
  289.         ELSE
  290.             BEGIN
  291.                 VRefNum := scPB.standardPB.scVRefNum;
  292.                 Logins := scPB.standardPB.scLogins;
  293.                 DirID := scPB.standardPB.scDirID;
  294.             END;
  295.     END;
  296.  
  297. {••• Test Code •••}
  298. { Enumerate the list of exported volumes and folders    }
  299.  
  300.     PROCEDURE GetAllExpFldrs;
  301.         VAR
  302.             Index: Integer;
  303.             shortName: Str13;
  304.             VRefNum: Integer;
  305.             Logins: Integer;
  306.             DirID: LongInt;
  307.             err: OSErr;
  308.     BEGIN
  309.         FOR Index := -gMaxVolumes TO gMaxExpFolders DO
  310.             IF Index <> 0 THEN { index 0 is undefined }
  311.                 BEGIN
  312.                     err := MySCGetExpFldr(@shortName, VRefNum, Logins, Index, DirID);
  313.                     IF err = noErr THEN
  314.                         BEGIN
  315.                             IF Index < 0 THEN
  316.                                 BEGIN
  317.                                     { do something with the exported volume }
  318.                                     { information }
  319.                                 END
  320.                             ELSE
  321.                                 BEGIN
  322.                                     { do something with the exported folder }
  323.                                     { information }
  324.                                 END;
  325.                         END
  326.                     ELSE IF err <> fnfErr THEN
  327.                         { fnfErr only means there is nothing at this }
  328.                         { Index position }
  329.                         BEGIN
  330.                             { handle any unexpected errors }
  331.                         END;
  332.                 END;
  333.     END;
  334.  
  335.  
  336. {-----------------------------------------------------------}
  337. { This function calls SCGetServerStatus to get the file        }
  338. { server's current status information.                        }
  339.  
  340.     FUNCTION MySCGetServerStatus (NamePtr: StringPtr;
  341.                                     VAR ServerFlags: Integer;
  342.                                     VAR NumSessions: Integer;
  343.                                     VAR UserListModDate: LongInt;
  344.                                     VAR Activity: Integer;
  345.                                     VAR VolListModDate: LongInt): OSErr;
  346.         VAR
  347.             scPB: SCParamBlockRec;
  348.     BEGIN
  349.         scPB.statusPB.scCode := SCGetServerStatus;
  350.         scPB.statusPB.scNamePtr := NamePtr;
  351.  
  352.         MySCGetServerStatus := SyncServerDispatch(@scPB);
  353.  
  354.         ServerFlags := scPB.statusPB.scServerFlags;
  355.         NumSessions := scPB.statusPB.scNumSessions;
  356.         UserListModDate := scPB.statusPB.scUserListModDate;
  357.         Activity := scPB.statusPB.scActivity;
  358.         VolListModDate := scPB.statusPB.scVolListModDate;
  359.     END;
  360.  
  361.  
  362. {-----------------------------------------------------------}
  363. { This function calls SCGetServerEventProc to get a            }
  364. { pointer to the head of the server event handler queue.    }
  365.  
  366.     FUNCTION MySCGetServerEventProc (VAR theSEQHdrPtr: QHdrPtr): OSErr;
  367.         VAR
  368.             scPB: SCParamBlockRec;
  369.     BEGIN
  370.         scPB.serverEventPB.scCode := SCGetServerEventProc;
  371.  
  372.         MySCGetServerEventProc := SyncServerDispatch(@scPB);
  373.  
  374.         theSEQHdrPtr := QHdrPtr(scPB.serverEventPB.scSEQEntryPtr);
  375.     END;
  376.  
  377. {••• Test Code •••}
  378. { Enumerate the list of installed server event handlers.    }
  379.  
  380.     PROCEDURE GetServerEventHandlers;
  381.         VAR
  382.             err: OSErr;
  383.             theSEQHdrPtr: QHdrPtr;
  384.             theSEQEntryPtr: tSEQEntryPtr;
  385.  
  386.     BEGIN
  387.         err := MySCGetServerEventProc(theSEQHdrPtr);
  388.         IF err = noErr THEN
  389.             BEGIN
  390.                 theSEQEntryPtr := tSEQEntryPtr(theSEQHdrPtr^.qHead);
  391.                 WHILE theSEQEntryPtr <> NIL DO
  392.                     BEGIN
  393.                         { do something with the tSEQentry pointed to }
  394.                         { by theSEQEntryPtr }
  395.  
  396.                         { move pointer to next entry (if any) }
  397.                         theSEQEntryPtr := tSEQEntryPtr(theSEQEntryPtr^.SEQentry.qLink);
  398.                     END;
  399.             END
  400.         ELSE
  401.             BEGIN
  402.                 { handle any errors }
  403.             END;
  404.     END;
  405.  
  406.  
  407. {-----------------------------------------------------------}
  408. { This function calls SCGetUserNameRec to retrieve            }
  409. { statistics on a connected user.                            }
  410.  
  411.     FUNCTION MySCGetUserNameRec (NamePtr: StringPtr;
  412.                                     VAR Position: LongInt;
  413.                                     VAR UNRecID: LongInt;
  414.                                     VAR UserID: LongInt;
  415.                                     VAR LoginTime: LongInt;
  416.                                     VAR LastUseTime: LongInt;
  417.                                     VAR SocketNum: AddrBlock): OSErr;
  418.         VAR
  419.             scPB: SCParamBlockRec;
  420.     BEGIN
  421.         scPB.userInfoPB.scCode := SCGetUserNameRec;
  422.         scPB.userInfoPB.scNamePtr := NamePtr;
  423.         scPB.userInfoPB.scPosition := Position;
  424.  
  425.         MySCGetUserNameRec := SyncServerDispatch(@scPB);
  426.  
  427.         Position := scPB.userInfoPB.scPosition;
  428.         UNRecID := scPB.userInfoPB.scUNRecID;
  429.         UserID := scPB.userInfoPB.scUserID;
  430.         LoginTime := scPB.userInfoPB.scLoginTime;
  431.         LastUseTime := scPB.userInfoPB.scLastUseTime;
  432.         SocketNum := scPB.userInfoPB.scSocketNum;
  433.     END;
  434.  
  435. {••• Test Code •••}
  436. { Enumerate the list of users logged on                        }
  437.  
  438.     PROCEDURE GetAllUserNameRecs;
  439.         VAR
  440.             err: OSErr;
  441.             UserName: Str31;
  442.             Position: LongInt;
  443.             UNRecID: LongInt;
  444.             UserID: LongInt;
  445.             LoginTime: LongInt;
  446.             LastUseTime: LongInt;
  447.             SocketNum: AddrBlock;
  448.     BEGIN
  449.         Position := 0;
  450.         REPEAT
  451.             err := MySCGetUserNameRec(@UserName, Position, UNRecID, UserID, LoginTime, LastUseTime, SocketNum);
  452.             IF err = noErr THEN
  453.                 BEGIN
  454.                     { do something with the user information returned }
  455.                 END
  456.             ELSE IF err <> fnfErr THEN
  457.                 { fnfErr only means there are no more users }
  458.                 BEGIN
  459.                     { handle any unexpected errors }
  460.                 END;
  461.         UNTIL err <> noErr;
  462.     END;
  463.  
  464.  
  465. {-----------------------------------------------------------}
  466. { This function calls SCGetUserMountInfo to return            }
  467. { information telling how a user is using a particular        }
  468. { volume or exported folder.                                }
  469.  
  470.     FUNCTION MySCGetUserMountInfo (VRefNum: Integer;
  471.                                     VAR FilesOpen: Integer;
  472.                                     VAR WriteableFiles: Integer;
  473.                                     UNRecID: LongInt;
  474.                                     VAR Mounted: Boolean;
  475.                                     VAR MountedAsOwner: Boolean): OSErr;
  476.         VAR
  477.             scPB: SCParamBlockRec;
  478.     BEGIN
  479.         scPB.volMountedPB.scCode := SCGetUserMountInfo;
  480.         scPB.volMountedPB.scVRefNum := VRefNum;
  481.         scPB.volMountedPB.scUNRecID := UNRecID;
  482.  
  483.         MySCGetUserMountInfo := SyncServerDispatch(@scPB);
  484.  
  485.         FilesOpen := scPB.volMountedPB.scFilesOpen;
  486.         WriteableFiles := scPB.volMountedPB.scWriteableFiles;
  487.         Mounted := scPB.volMountedPB.scMounted;
  488.         MountedAsOwner := scPB.volMountedPB.scMountedAsOwner;
  489.     END;
  490.  
  491. {••• Test Code •••}
  492. { Get the user mount information for all volumes and        }
  493. { exported folders a user has mounted.                        }
  494.  
  495.     PROCEDURE GetAllUserMountInfo (UNRecID: LongInt);
  496.         VAR
  497.             err: OSErr;
  498.             Index: Integer;
  499.             VRefNum: Integer;
  500.             FilesOpen: Integer;
  501.             WriteableFiles: Integer;
  502.             Mounted: Boolean;
  503.             MountedAsOwner: Boolean;
  504.     BEGIN
  505.         FOR Index := -gMaxVolumes TO gMaxExpFolders DO
  506.             IF Index <> 0 THEN { index 0 is undefined }
  507.                 BEGIN
  508.                     err := MySCGetUserMountInfo(Index, FilesOpen, WriteableFiles, UNRecID, Mounted, MountedAsOwner);
  509.                     IF (err = noErr) AND Mounted THEN
  510.                         BEGIN
  511.                             { do something with the information returned }
  512.                         END;
  513.                 END;
  514.     END;
  515.  
  516.  
  517. {-----------------------------------------------------------}
  518. { This function calls SCStartServer to start the Macintosh    }
  519. { File Sharing server.                                        }
  520.  
  521.     FUNCTION MySCStartServer: OSErr;
  522.         VAR
  523.             scPB: SCParamBlockRec;
  524.     BEGIN
  525.         scPB.startPB.scCode := SCStartServer;
  526.         scPB.startPB.scStartSelect := kCurInstalled;
  527.         scPB.startPB.scEventSelect := kFinderExtn;
  528.  
  529.         MySCStartServer := SyncServerDispatch(@scPB);
  530.     END;
  531.  
  532.  
  533. {-----------------------------------------------------------}
  534. { This function calls SCShutDown to shut down the file        }
  535. { server.                                                    }
  536.  
  537.     FUNCTION MySCShutDown (NumMinutes: Integer;
  538.                                     Flags: Integer;
  539.                                     MessagePtr: StringPtr): OSErr;
  540.         VAR
  541.             scPB: SCParamBlockRec;
  542.     BEGIN
  543.         scPB.disconnectPB.scCode := SCShutDown;
  544.         scPB.disconnectPB.scNumMinutes := NumMinutes;
  545.         scPB.disconnectPB.scFlags := Flags;
  546.         scPB.disconnectPB.scMessagePtr := MessagePtr;
  547.  
  548.         MySCShutDown := SyncServerDispatch(@scPB);
  549.     END;
  550.  
  551.  
  552. {-----------------------------------------------------------}
  553. { This function calls SCCancelShutDown to cancel the        }
  554. { shutdown or disconnect in progress.                        }
  555.  
  556.     FUNCTION MySCCancelShutDown: OSErr;
  557.         VAR
  558.             scPB: SCParamBlockRec;
  559.     BEGIN
  560.         scPB.disconnectPB.scCode := SCCancelShutDown;
  561.  
  562.         MySCCancelShutDown := SyncServerDispatch(@scPB);
  563.     END;
  564.  
  565.  
  566. {-----------------------------------------------------------}
  567. { This function calls SCWakeServer to wake up a sleeping    }
  568. { AppleShare 3.0 file server.                                }
  569.  
  570.     FUNCTION MySCWakeServer: OSErr;
  571.         VAR
  572.             scPB: SCParamBlockRec;
  573.     BEGIN
  574.         scPB.startPB.scCode := SCWakeServer;
  575.  
  576.         MySCWakeServer := SyncServerDispatch(@scPB);
  577.     END;
  578.  
  579.  
  580. {-----------------------------------------------------------}
  581. { This function calls SCSleepServer to shut down the file    }
  582. { server temporarily.                                        }
  583.  
  584.     FUNCTION MySCSleepServer (NumMinutes: Integer;
  585.                                     Flags: Integer;
  586.                                     MessagePtr: StringPtr): OSErr;
  587.         VAR
  588.             scPB: SCParamBlockRec;
  589.     BEGIN
  590.         scPB.disconnectPB.scCode := SCSleepServer;
  591.         scPB.disconnectPB.scNumMinutes := NumMinutes;
  592.         scPB.disconnectPB.scFlags := Flags;
  593.         scPB.disconnectPB.scMessagePtr := MessagePtr;
  594.  
  595.         MySCSleepServer := SyncServerDispatch(@scPB);
  596.     END;
  597.  
  598.  
  599. {-----------------------------------------------------------}
  600. { This function calls SCSetSetupInfo to set the file        }
  601. { server's setup information.                                }
  602.  
  603.     FUNCTION MySCSetSetupInfo (SetupPtr: SetupInfoRecPtr): OSErr;
  604.         VAR
  605.             scPB: SCParamBlockRec;
  606.     BEGIN
  607.         scPB.setupPB.scCode := SCSetSetupInfo;
  608.         scPB.setupPB.scSetupPtr := SetupPtr;
  609.  
  610.         MySCSetSetupInfo := SyncServerDispatch(@scPB);
  611.     END;
  612.  
  613.  
  614. {-----------------------------------------------------------}
  615. { This function calls SCDisconnect to disconnect some        }
  616. { users. Although Macintosh File Sharing implements            }
  617. { SCDisconnect, there is no way to use it with File            }
  618. { Sharing because File Sharing doesn't implement the        }
  619. { SCGetUserNameRec call.                                    }
  620.  
  621.     FUNCTION MySCDisconnect (DiscArrayPtr: LongIntPtr;
  622.                                     ArrayCount: Integer;
  623.                                     NumMinutes: Integer;
  624.                                     Flags: Integer;
  625.                                     MessagePtr: StringPtr): OSErr;
  626.         VAR
  627.             scPB: SCParamBlockRec;
  628.     BEGIN
  629.         scPB.disconnectPB.scDiscArrayPtr := DiscArrayPtr;
  630.         scPB.disconnectPB.scArrayCount := ArrayCount;
  631.         scPB.disconnectPB.scCode := SCDisconnect;
  632.         scPB.disconnectPB.scNumMinutes := NumMinutes;
  633.         scPB.disconnectPB.scFlags := Flags;
  634.         scPB.disconnectPB.scMessagePtr := MessagePtr;
  635.  
  636.         MySCDisconnect := SyncServerDispatch(@scPB);
  637.     END;
  638.  
  639. {••• Test Code •••}
  640. { Disconnect the user specified in 10 minutes with a        }
  641. { message.                                                    }
  642.  
  643.     PROCEDURE DisconnectUser (UNRecID: LongInt);
  644.         VAR
  645.             err: OSErr;
  646.             ArrayCount: Integer;
  647.             NumMinutes: Integer;
  648.             Flags: Integer;
  649.             Message: tLoginMsg;
  650.     BEGIN
  651.         ArrayCount := 1;  { one user }
  652.         NumMinutes := 10;
  653.         Flags := UNRFSendMsgMask; { send a message }
  654.         Message := 'Goodbye.';
  655.         err := MySCDisconnect(@UNRecID, ArrayCount, NumMinutes, Flags, @Message);
  656.         IF err = noErr THEN
  657.             { the disconnect was started }
  658.         ELSE
  659.             BEGIN
  660.                 { handle any errors }
  661.             END;
  662.     END;
  663.  
  664.  
  665. {-----------------------------------------------------------}
  666. { This function calls SCSendMessage to send a message to    }
  667. { some users.                                                }
  668.  
  669.     FUNCTION MySCSendMessage (DiscArrayPtr: LongIntPtr;
  670.                                     ArrayCount: Integer;
  671.                                     Flags: Integer;
  672.                                     MessagePtr: StringPtr): OSErr;
  673.         VAR
  674.             scPB: SCParamBlockRec;
  675.     BEGIN
  676.         scPB.disconnectPB.scDiscArrayPtr := DiscArrayPtr;
  677.         scPB.disconnectPB.scArrayCount := ArrayCount;
  678.         scPB.disconnectPB.scCode := SCSendMessage;
  679.         scPB.disconnectPB.scFlags := Flags;
  680.         scPB.disconnectPB.scMessagePtr := MessagePtr;
  681.  
  682.         MySCSendMessage := SyncServerDispatch(@scPB);
  683.     END;
  684.  
  685. {••• Test Code •••}
  686. { Send a message to all connected users                        }
  687.  
  688.     PROCEDURE SendMessageToAll;
  689.     { This routine depends on gCurMaxSessions being }
  690.     { initialized with SCGetSetupInfo. }
  691.         VAR
  692.             err: OSErr;
  693.             ArrayPosPtr: LongIntPtr;
  694.             scPB: SCParamBlockRec;
  695.  
  696.             DiscArrayPtr: LongIntPtr;
  697.             ArrayCount: Integer;
  698.             Flags: Integer;
  699.             Message: tLoginMsg;
  700.     BEGIN
  701.         { allocate an array large enough to get all users }
  702.         DiscArrayPtr := LongIntPtr(NewPtr(sizeof(LongInt) * gCurMaxSessions));
  703.         IF DiscArrayPtr <> NIL THEN
  704.             BEGIN
  705.                 scPB.userInfoPB.scPosition := 0;
  706.                 ArrayCount := 0;
  707.                 ArrayPosPtr := DiscArrayPtr;
  708.                 REPEAT
  709.                     { build list of users with SCGEtUserNameRec }
  710.                     scPB.userInfoPB.scCode := SCGetUserNameRec;
  711.                     scPB.userInfoPB.scNamePtr := NIL;
  712.                     err := SyncServerDispatch(@scPB);
  713.                     IF err = noErr THEN
  714.                         BEGIN { add user to array }
  715.                             ArrayPosPtr^ := scPB.userInfoPB.scUNRecID;
  716.                             ArrayPosPtr := LongIntPtr(ORD4(ArrayPosPtr) + sizeof(LongInt));
  717.                             ArrayCount := ArrayCount + 1;
  718.                         END;
  719.                 UNTIL err <> noErr;
  720.                 IF ArrayCount > 0 THEN
  721.                     BEGIN
  722.                         Flags := UNRFSendMsgMask; { send a message }
  723.                         Message := 'Moof!t';
  724.                         err := MySCSendMessage(DiscArrayPtr, ArrayCount, Flags, @Message);
  725.                         IF err = noErr THEN
  726.                             { the message was sent }
  727.                         ELSE
  728.                             BEGIN
  729.                                 { handle any errors from SCSendMessage }
  730.                             END
  731.                     END
  732.                 ELSE  { there are no users connected }
  733.                     ;   { do nothing }
  734.                 DisposPtr(Ptr(DiscArrayPtr));
  735.             END
  736.         ELSE
  737.             BEGIN
  738.                 { handle memory manager error }
  739.             END;
  740.     END;
  741.  
  742.  
  743. {-----------------------------------------------------------}
  744. { This function calls SCSetCopyProtect to set the copy        }
  745. { protect status of a file.                                    }
  746.  
  747.     FUNCTION MySCSetCopyProtect (NamePtr: StringPtr;
  748.                                     VRefNum: Integer;
  749.                                     DirID: LongInt): OSErr;
  750.         VAR
  751.             scPB: SCParamBlockRec;
  752.     BEGIN
  753.         scPB.standardPB.scNamePtr := NamePtr;
  754.         scPB.standardPB.scVRefNum := VRefNum;
  755.         scPB.standardPB.scCode := SCSetCopyProtect;
  756.         scPB.standardPB.scDirID := DirID;
  757.  
  758.         MySCSetCopyProtect := SyncServerDispatch(@scPB);
  759.     END;
  760.  
  761.  
  762. {-----------------------------------------------------------}
  763. { This function calls SCClrCopyProtect to clear the copy    }
  764. { protect status of a file.                                    }
  765.  
  766.     FUNCTION MySCClrCopyProtect (NamePtr: StringPtr;
  767.                                     VRefNum: Integer;
  768.                                     DirID: LongInt): OSErr;
  769.         VAR
  770.             scPB: SCParamBlockRec;
  771.     BEGIN
  772.         scPB.standardPB.scNamePtr := NamePtr;
  773.         scPB.standardPB.scVRefNum := VRefNum;
  774.         scPB.standardPB.scCode := SCClrCopyProtect;
  775.         scPB.standardPB.scDirID := DirID;
  776.  
  777.         MySCClrCopyProtect := SyncServerDispatch(@scPB);
  778.     END;
  779.  
  780.  
  781. {-----------------------------------------------------------}
  782. { This function calls SCDisconnectVolUsers to disconnect    }
  783. { the users of specified volumes.                            }
  784.  
  785.     FUNCTION MySCDisconnectVolUsers (DiscArrayPtr: LongIntPtr;
  786.                                     ArrayCount: Integer;
  787.                                     NumMinutes: Integer;
  788.                                     Flags: Integer;
  789.                                     MessagePtr: StringPtr): OSErr;
  790.         VAR
  791.             scPB: SCParamBlockRec;
  792.     BEGIN
  793.         scPB.disconnectPB.scDiscArrayPtr := DiscArrayPtr;
  794.         scPB.disconnectPB.scArrayCount := ArrayCount;
  795.         scPB.disconnectPB.scCode := SCDisconnectVolUsers;
  796.         scPB.disconnectPB.scNumMinutes := NumMinutes;
  797.         scPB.disconnectPB.scFlags := Flags;
  798.         scPB.disconnectPB.scMessagePtr := MessagePtr;
  799.  
  800.         MySCDisconnectVolUsers := SyncServerDispatch(@scPB);
  801.     END;
  802.  
  803. {••• Test Code •••}
  804. { Disconnect the users of the specified volume in            }
  805. { 10 minutes with a message.                                }
  806.  
  807.     PROCEDURE DisconnectVolUsers (VRefNum: Integer);
  808.         VAR
  809.             err: OSErr;
  810.  
  811.             DiscToDisconnect: LongInt;
  812.             ArrayCount: Integer;
  813.             NumMinutes: Integer;
  814.             Flags: Integer;
  815.             Message: tLoginMsg;
  816.     BEGIN
  817.         DiscToDisconnect := VRefNum; { note: Integer -> LongInt }
  818.         ArrayCount := 1;
  819.         NumMinutes := 10;
  820.         Flags := UNRFSendMsgMask; { send a message }
  821.         Message := 'A volume is going away.';
  822.         err := MySCDisconnectVolUsers(@DiscToDisconnect, ArrayCount, NumMinutes, Flags, @Message);
  823.         IF err = noErr THEN
  824.             { the disconnect was started }
  825.         ELSE
  826.             BEGIN
  827.                 { handle any errors }
  828.             END;
  829.     END;
  830.  
  831.  
  832. {==========================================================}
  833.  
  834. BEGIN { main }
  835.  
  836.     { You MUST make sure ServerDispatch is available before calling it }
  837.     gHasServerDispatch := TrapAvailable(ServerDispatch);
  838.     IF gHasServerDispatch THEN
  839.         BEGIN
  840.  
  841.             gErr := MySCServerVersion(@gServerExtensionName, gServerType, gServerVersion);
  842.  
  843.             gErr := MySCPollServer(gServerState, gDisconnectState, gServerError, gSecondsLeft);
  844.  
  845.             gErr := MySCGetSetupInfo(@gSetupInfoRec, gMaxVolumes, gMaxExpFolders, gCurMaxSessions);
  846.         END;
  847.  
  848. END. { main }